package nl.Viewer.ViewManager.Objects;

import java.util.ArrayList;

import nl.Viewer.ViewManager.Controllers.GenericController;

public class SynchronizableControllersCollection {
   private ArrayList<ControllerPair> pairs = new ArrayList<ControllerPair>();

   /**
    * This method will add a new pair based on the provided objects. The method will return immediately when the pair is
    * already present.
    * 
    * @param o1
    * @param o2
    */
   public synchronized void addPair( GenericController c1, GenericController c2 ) {
      if( c1 == c2 )
         return; // don't allow pairs of the same object

      if( findPair( c1, c2 ) != null )
         return; // pair already exists

      // construct the objectTuple with object with lowest hashcode first
      if( c1.hashCode() > c2.hashCode() ) {
         GenericController t = c1;
         c1 = c2;
         c2 = t;
      }

      pairs.add( new ControllerPair( new ControllerObject( c1, false ), new ControllerObject( c2, false ) ) );
   }

   public synchronized ArrayList<ControllerPair> findPairsForController( GenericController o ) {
      ArrayList<ControllerPair> pairedObjects = new ArrayList<ControllerPair>();
      for( ControllerPair cp : pairs ) {
         if( cp.getObject1().getController() == o || cp.getObject2().getController() == o )
            pairedObjects.add( cp );
      }
      return pairedObjects;
   }

   /**
    * This method will return the tuple of the two given objects (which can be specified in either order)
    * 
    * @param o1
    * @param o2
    * @return
    */
   public synchronized ControllerPair findPair( GenericController o1, GenericController o2 ) {
      // we know pairs are always inserted with the object with lowest hashcode first
      if( o1.hashCode() > o2.hashCode() ) {
         GenericController t = o1;
         o1 = o2;
         o2 = t;
      }
      for( ControllerPair cp : pairs ) {
         if( cp.getObject1().getController() == o1 && cp.getObject2().getController() == o2 ) {
            return cp;
         }
      }
      return null;
   }

   /**
    * This method will remove all pairs containing the object
    * 
    * @param o
    */
   public synchronized void removeController( GenericController o ) {
      int i = 0;
      ControllerPair cp;
      // in-place remove of the pairs containing the object
      while( i < pairs.size() ) {
         cp = pairs.get( i );
         if( cp.getObject1().getController() == o || cp.getObject2().getController() == o ) {
            System.out.println( "PairCollection removing tuple " + cp + " for object " + o );
            pairs.remove( i );
         } else {
            // only increment when we don't remove an object
            i++;
         }
      }
   }

   public synchronized int size() {
      return pairs.size();
   }

}
